﻿using System.Collections.Generic;
using System;
using System.Drawing;
using Dataweb.NShape.Advanced;
using Dataweb.NShape;
using System.ComponentModel;
using cz.zcu.PreSti.Components;

namespace cz.zcu.PreSti.Shapes
{
    public class SetterSymbol : RectangleBase, ISymbol
    {
        protected override void InitializeToDefault(IStyleSet styleSet)
        {
            base.InitializeToDefault(styleSet);
            Height = 30;
            Width = 20;
        }

        public override Shape Clone()
        {
            Shape result = new SetterSymbol(Type, (Template)null);
            result.CopyFrom(this);
            return result;
        }

        protected override int ControlPointCount
        {
            get { return ActionsCount + EventsCount + SettersCount + GettersCount; }
        }

        public override bool HasControlPointCapability(ControlPointId controlPointId, ControlPointCapabilities controlPointCapability)
        {
            if (controlPointId > 0 && controlPointId < ActionsCount + EventsCount + SettersCount + GettersCount + 1)
                return ((controlPointCapability & ControlPointCapabilities.Connect) != 0);
            else return base.HasControlPointCapability(controlPointId, controlPointCapability);
        }


        protected internal SetterSymbol(ShapeType shapeType, Template template)
            : base(shapeType, template)
        {
        }


        protected override void CalcControlPoints()
        {

            int left = (int)Math.Round(-Width / 2f);
            int top = (int)Math.Round(-Height / 2f);
            int right = left + Width;
            int bottom = top + Height;

            ControlPoints[0].X = left + Width / 2;
            ControlPoints[0].Y = bottom;
        }


        protected override void CalcCaptionBounds(int index, out Rectangle captionBounds)
        {
            if (index != 0) throw new IndexOutOfRangeException();
            int left = (int)Math.Round(-Width / 2f);
            int top = (int)Math.Round(-Height / 2f);
            captionBounds = Rectangle.Empty;
            captionBounds.X = left;
            captionBounds.Y = top;
            captionBounds.Width = Width;
            captionBounds.Height = Height;
        }


        protected override bool CalculatePath()
        {
            if (base.CalculatePath())
            {
                int left = (int)Math.Round(-Width / 2f);
                int top = (int)Math.Round(-Height / 2f);
                int right = left + Width;
                int bottom = top + Height;

                PointF[] points = new PointF[3];
                points[0].X = left;
                points[0].Y = top;
                points[1].X = left + connectorWidth;
                points[1].Y = bottom;
                points[2].X = right - connectorWidth;
                points[2].Y = bottom;

                Path.Reset();
                Path.StartFigure();
                Path.AddLine(right - connectorWidth, bottom, right, top);
                Path.AddLines(points);
                Path.AddCurve(new PointF[] { new PointF(-4, bottom), new PointF(0, bottom - 4), new PointF(4, bottom) }, 1);
                Path.CloseFigure();
                return true;
            }
            return false;
        }


        #region Fields
        private int connectorWidth = 5;
        #endregion


        #region ISymbol Members

        public BaseComponent initializeComponent(IPresentation p)
        {
            SetterModel model = (SetterModel)this.ModelObject;
            Setter setter = new Setter(p);
            setter.Value = model.DefaultValue;
            setter.SetterIndex = model.SetterIndex - 1;
            return setter;
        }

        public virtual int ActionsCount
        {
            get { return 0; }
        }

        public virtual int EventsCount
        {
            get { return 0; }
        }

        public virtual int SettersCount
        {
            get { return 0; }
        }

        public virtual int GettersCount
        {
            get { return 1; }
        }

        public virtual string GetTitleForAction(int id)
        {
            return null;
        }

        public virtual string GetTitleForEvent(int id)
        {
            return null;
        }

        public virtual string GetTitleForSetter(int id)
        {
            return null;
        }

        public virtual string GetTitleForGetter(int id)
        {
            switch (id)
            {
                case 0:
                    return "Value provided into diagram by Setter";
            }
            return null;
        }

        #endregion

        internal static Shape CreateInstance(ShapeType shapeType, Template template)
        {
            return new SetterSymbol(shapeType, template);
        }

    }

    public class SetterModel : ModelObjectBase
    {

        #region Fields

        private int setterIndex = 1;
        //private string setterName = "";
        private string defaultValue = "";
        private char securityDomainName = 'A';

        private const int PropertyIdSetterIndex = 1;
        //private const int PropertyIdSetterName = 2;
        private const int PropertyIdDefaultValue = 3;

        #endregion

        #region properties

        [Category("Presentation")]
        [Description("Numeric order of this setter at subdiagram symbol.")]
        [PropertyMappingId(PropertyIdSetterIndex)]
        public virtual int SetterIndex
        {
            get
            {
                return setterIndex;
            }
            set
            {
                if (value < 1) value = 1;
                else if (value > 7) value = 7;
                setterIndex = value;
            }
        }

        /*
        [Category("Presentation")]
        [Description("Description of this setter used on subdiagram symbol.")]
        [PropertyMappingId(PropertyIdSetterName)]
        public virtual string SetterName
        {
            get
            {
                return setterName;
            }
            set
            {
                setterName = value;
            }
        }
        */

        [Category("Presentation")]
        [Description("Default input value for this setter.")]
        [PropertyMappingId(PropertyIdDefaultValue)]
        public virtual string DefaultValue
        {
            get
            {
                return defaultValue;
            }
            set
            {
                defaultValue = value;
            }
        }

        #endregion

        public static SetterModel CreateInstance(ModelObjectType modelObjectType)
        {
            return new SetterModel(modelObjectType);
        }


        protected internal SetterModel(ModelObjectType modelObjectType)
            : base(modelObjectType)
        {
            this.terminalCount = 1;
        }


        protected internal SetterModel(SetterModel source)
            : base(source)
        {
            SetterIndex = source.SetterIndex;
            //SetterName = source.SetterName;
            DefaultValue = source.DefaultValue;
            this.terminalCount = 1;
        }


        public override IModelObject Clone()
        {
            return new SetterModel(this);
        }


        public override IEnumerable<MenuItemDef> GetMenuItemDefs()
        {
            throw new NotImplementedException();
        }


        public override void Connect(TerminalId ownTerminalId, IModelObject targetConnector, TerminalId targetTerminalId)
        {
        }


        public override void Disconnect(TerminalId ownTerminalId, IModelObject targetConnector, TerminalId targetTerminalId)
        {
        }

        public override char SecurityDomainName
        {
            get { return securityDomainName; }
            set
            {
                if (value < 'A' || value > 'Z')
                    throw new ArgumentOutOfRangeException("SecurityDomainName", "The domain qualifier has to be an upper case  ANSI letter (A-Z).");
                securityDomainName = value;
            }
        }


        #region IEntity Members

        public static new IEnumerable<EntityPropertyDefinition> GetPropertyDefinitions(int version)
        {
            foreach (EntityPropertyDefinition pi in ModelObjectBase.GetPropertyDefinitions(version))
                yield return pi;
            yield return new EntityFieldDefinition("SetterIndex", typeof(int));
            //yield return new EntityFieldDefinition("SetterName", typeof(string));
            yield return new EntityFieldDefinition("DefaultValue", typeof(string));
        }

        protected override void LoadFieldsCore(IRepositoryReader reader, int version)
        {
            base.LoadFieldsCore(reader, version);
            SetterIndex = reader.ReadInt32();
            //SetterName = reader.ReadString();
            DefaultValue = reader.ReadString();
        }

        protected override void SaveFieldsCore(IRepositoryWriter writer, int version)
        {
            base.SaveFieldsCore(writer, version);
            writer.WriteInt32(SetterIndex);
            //writer.WriteString(SetterName);
            writer.WriteString(DefaultValue);
        }

        #endregion
    }


}